/**
This file defines asm functions.
**/

#define Mode_USR 0x10
#define Mode_FIQ 0x11
#define Mode_IRQ 0x12
#define Mode_SVC 0x13
#define Mode_MON 0x16
#define Mode_ABT 0x17
#define Mode_HYP 0x1a
#define Mode_UND 0x1b
#define Mode_SYS 0x1f
#define I_Bit    0x80
#define F_Bit    0x40

.global arch_get_cpuid
///**
// * @brief Get the core id.
// * @return int 
// */
arch_get_cpuid:
    mrc     p15, 0, r0, c0, c0, 5
    and     r0, r0, #0x03
    mov     pc, lr

//addr,old,new
.global arch_compare_and_swap
///**
// * compare and swap
// * @brief arch_cas_lock(*lock, old, new)
// */
arch_compare_and_swap:
    ldrex   r3, [r0]
    cmp     r1, r3
    bne     _cas_fail
    strex   r3, r2, [r0]
    cmp     r3, #0
    bne     _cas_fail
    mov     r0, #1
    mov     pc, lr
_cas_fail:
    mov     r0, #0
    mov     pc, lr
     

// The following is limited to current module
.global join_smp
join_smp:
    MRC     p15, 0, r0, c1, c0, 1   // Read ACTLR
    MOV     r1, r0
    ORR     r0, r0, #0x040          // Set bit 6
    CMP     r0, r1
    MCRNE   p15, 0, r0, c1, c0, 1   // Write ACTLR
    ISB
    mov     pc, lr

.global disjoin_smp
disjoin_smp:
    mrc p15, 0, r0, c1, c0, 1     // read ACTLR
    bic r0,  r0, #0x040           // clear bit 6
    mcr p15, 0, r0, c1, c0, 1     // write to ACTLR
    mov pc, lr

.global enable_l1_cache
enable_l1_cache:
    MRC p15, 0, r1, c1, c0, 0
    orr r1, r1, #(0x1 << 12)
    orr r1, r1, #(0x1 << 2)
    MCR p15, 0, r1, c1, c0, 0
    ISB
    mov pc, lr

.global disable_l1_cache
disable_l1_cache:
    MRC p15, 0, r1, c1, c0, 0
    BIC r1, r1, #(0x1 << 12)
    BIC r1, r1, #(0x1 << 2)
    MCR p15, 0, r1, c1, c0, 0
    mov pc, lr


.global get_pheriphal_addr
get_pheriphal_addr:
    mrc     p15, 4, r0, c15, c0, 0
    mov     pc, lr

.global enable_scu
enable_scu:
    // void enable_scu(void)
    mrc p15, 4, r0, c15, c0, 0
    ldr r1, [r0]        // Read periph base address
    orr r1, r1, #0x1    // Set bit 0 (The Enable bit)
    str r1, [r0]        // Write back modifed value
    mov pc, lr

.global enable_core_int
enable_core_int:
    mrs r0, cpsr
    bic r0, r0, #I_Bit
    msr cpsr, r0
    mov pc, lr


.global send_ici
// void send_ici(id, target_list, filter_list)
// Send a software generate interrupt
send_ici:

  AND     r3, r0, #0x0F           // Mask off unused bits of ID, and move to r3
  AND     r1, r1, #0x0F           // Mask off unused bits of target_filter
  AND     r2, r2, #0x0F           // Mask off unused bits of filter_list

  ORR     r3, r3, r1, LSL #16     // Combine ID and target_filter
  ORR     r3, r3, r2, LSL #24     // and now the filter list

  // Get the address of the GIC
  MRC     p15, 4, r0, c15, c0, 0  // Read periph base address
  ADD     r0, r0, #0x1F00         // Add offset of the sgi_trigger reg

  STR     r3, [r0]                // Write to the Software Generated Interrupt Register (ICDSGIR)
  mov     pc, lr